package com.crowbar.map.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crowbar.map.entity.*;
import com.crowbar.map.mapper.EventsInfoMapper;
import com.crowbar.map.mapper.LocationInfoMapper;
import com.crowbar.map.mapper.MapInfoMapper;
import com.crowbar.map.service.MapInfoService;
//import org.json.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * (MapInfo)表服务实现类
 *
 * @author makejava
 * @since 2025-01-03 16:31:21
 */
@Service("mapInfoService")
public class MapInfoServiceImpl extends ServiceImpl<MapInfoMapper, MapInfo> implements MapInfoService {



    @Resource
    private MapInfoMapper MapInfoMapper;
    @Resource
    private LocationInfoMapper LocationInfoMapper;
    @Resource
    private EventsInfoMapper EventsInfoMapper;

    @Override
    public List<LocationInfo> getCitys(EventsInfoReq eventsInfoReq) {
        return LocationInfoMapper.getCitys(eventsInfoReq);
    }

    @Override
    public Map<String, List<MapInfo>> getMapInfo(MapInfoReq mapInfoReq) {
//        List result = new ArrayList();
//        if (startDate == "")
//            return result;
        // 转换startDate和endDate
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date start = null;
        Date end = null;
        try {
            start = (mapInfoReq.getStartDate() != null) ? simpleDateFormat.parse(mapInfoReq.getStartDate()) : null;
            end = (mapInfoReq.getEndDate() != null) ? simpleDateFormat.parse(mapInfoReq.getEndDate()) : null;
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

        LambdaQueryWrapper<MapInfo> queryWrapper = new LambdaQueryWrapper<>();
        if (start != null) {
            queryWrapper.ge(MapInfo::getItemAccessTime, start); // 大于等于起始时间
        }
        if (end != null) {
            queryWrapper.le(MapInfo::getItemAccessTime, end); // 小于等于终止时间
        }
        // 如果citys不为空，添加城市筛选条件
        if (mapInfoReq.getCitys()!= null && mapInfoReq.getCitys().length > 0) {
            queryWrapper.in(MapInfo::getCity, mapInfoReq.getCitys()); // 使用in进行城市筛选
        }
        if (mapInfoReq.getKeywords()!= null && mapInfoReq.getKeywords().length > 0) {
            queryWrapper.in(MapInfo::getKeywords, mapInfoReq.getKeywords()); // 使用in进行城市筛选
        }
        queryWrapper.last("LIMIT 5000");
        List<MapInfo> list = MapInfoMapper.selectList(queryWrapper);
        for(MapInfo mapInfo : list){
            if(mapInfo.getCity().contains("州")){
                mapInfo.setCity(mapInfo.getCity().split("州")[1]);
            }
        }

        // 根据国家进行分类
//        Map<String, List<MapInfo>> countryMap = list.stream()
//                .collect(Collectors.groupingBy(MapInfo::getCountry));

        Map<String, List<MapInfo>> countryMap = list.stream()
                .collect(Collectors.groupingBy(
                        MapInfo::getCountry,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                subList -> {
                                    subList.sort((a, b) -> (b.getItemLikeNum()+b.getItemCommentNum()+b.getItemShareNum() + b.getItemViewNum()) - (a.getItemLikeNum()+a.getItemCommentNum()+a.getItemShareNum() + a.getItemViewNum())); // 按num降序排序
                                    return subList;
                                }
                        )
                ));

//        List<MapInfo> list = MapInfoMapper.selectList(queryWrapper);

        return  countryMap;
    }

    @Override
    public Boolean addEvent(EventsInfoReq eventsInfoReq) {
        Boolean flag = false;
        LambdaQueryWrapper<EventsInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EventsInfo::getEventName, eventsInfoReq.getEventName());
        List<EventsInfo> eventsInfoList = EventsInfoMapper.selectList(queryWrapper);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

        Date start = null;
        Date end = null;
        Double lat = null;
        Double lnt = null;
        try {
            start = simpleDateFormat.parse(eventsInfoReq.getStartDate());
            end = simpleDateFormat.parse(eventsInfoReq.getEndDate());
            if(!StringUtils.isEmpty(eventsInfoReq.getEventLocation())){
                double[] coordinates = getCoordinates(eventsInfoReq.getEventLocation());
                if (coordinates != null) {
                    lat =  coordinates[0];
                    lnt =  coordinates[1];
                }
            }
        } catch (ParseException | IOException e) {
            throw new RuntimeException(e);
        }
        if(eventsInfoList.size()>0){
            // update
            // 应该只有一个
            EventsInfo eventsInfo = eventsInfoList.get(0);
            if(start != null){
                eventsInfo.setStartDate(start);
            }
            if(end != null){
                eventsInfo.setEndDate(end);
            }
            if(lat != null){
                eventsInfo.setLat(lat);
            }
            if(lnt != null){
                eventsInfo.setLng(lnt);
            }
            eventsInfo.setKeywords(String.join(",", eventsInfoReq.getKeywords()));
            flag = EventsInfoMapper.updateById(eventsInfo)>0;
        }else{
            EventsInfo eventsInfo = new EventsInfo();
            eventsInfo.setEventName(eventsInfoReq.getEventName());
            if(start != null){
                eventsInfo.setStartDate(start);
            }
            if(end != null){
                eventsInfo.setEndDate(end);
            }
            if(lat != null){
                eventsInfo.setLat(lat);
            }
            if(lnt != null){
                eventsInfo.setLng(lnt);
            }
            eventsInfo.setKeywords(String.join(",", eventsInfoReq.getKeywords()));
            flag =  EventsInfoMapper.insert(eventsInfo)>0;
        }
        return flag;
    }
    private static final String API_KEY = "d51eb55d041b49f8b6b9a65c5513e3a5"; // 替换为你的API Key
    private static final String BASE_URL = "https://api.opencagedata.com/geocode/v1/json";

    public static double[] getCoordinates(String countryName) throws IOException {
        String url = String.format("%s?q=%s&key=%s", BASE_URL, countryName, API_KEY);

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet request = new HttpGet(url);
            try (CloseableHttpResponse response = httpClient.execute(request)) {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    String result = EntityUtils.toString(entity);
                    ObjectMapper objectMapper = new ObjectMapper();
                    JsonNode rootNode = objectMapper.readTree(result);
                    JsonNode resultsNode = rootNode.path("results");
                    if (resultsNode.isArray() && resultsNode.size() > 0) {
                        JsonNode firstResult = resultsNode.get(0);
                        double lat = firstResult.path("geometry").path("lat").asDouble();
                        double lng = firstResult.path("geometry").path("lng").asDouble();
                        return new double[]{lat, lng};
                    }
                }
            }
        }
        return null;
    }

    @Override
    public List<EventsInfo> getEventByName(EventsInfoReq eventsInfoReq) throws ParseException {
        List<EventsInfo> eventsInfoList = new ArrayList<>();
        LambdaQueryWrapper<EventsInfo> queryWrapper = new LambdaQueryWrapper<>();
        if(!Objects.isNull(eventsInfoReq.getEventName())){
            queryWrapper.eq(EventsInfo::getEventName,eventsInfoReq.getEventName());
        }
        EventsInfo eventsInfo = EventsInfoMapper.selectList(queryWrapper).get(0); //只有一个
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long diffDay = TimeUnit.DAYS.convert(Math.abs(simpleDateFormat.parse(eventsInfoReq.getEndDate()).getTime() - simpleDateFormat.parse(eventsInfoReq.getStartDate()).getTime()), TimeUnit.MILLISECONDS);
        if(diffDay < 30){
            //前7天按天给，后面的按周
            if(diffDay < 7){
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(simpleDateFormat.parse(eventsInfoReq.getStartDate()));
                for(int i =0;i<diffDay ;i++){
                    EventsInfo dayInfo = new EventsInfo();
                    dayInfo.setStartDate(calendar.getTime());
                    dayInfo.setEndDate(calendar.getTime());
                    eventsInfoList.add(dayInfo);
                    calendar.add(Calendar.DAY_OF_MONTH, 1);
                }
            }else{
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(simpleDateFormat.parse(eventsInfoReq.getStartDate()));
                // 前七天每天一条记录
                for (int i = 0; i < 7; i++) {
                    EventsInfo dayInfo = new EventsInfo();
                    dayInfo.setStartDate(calendar.getTime());
                    dayInfo.setEndDate(calendar.getTime());
                    eventsInfoList.add(dayInfo);
                    calendar.add(Calendar.DAY_OF_MONTH, 1);
                }

                // 之后每周一条记录
                while (calendar.getTime().before(simpleDateFormat.parse(eventsInfoReq.getEndDate()))) {
                    EventsInfo dayInfo = new EventsInfo();
                    dayInfo.setStartDate(calendar.getTime());
                    calendar.add(Calendar.WEEK_OF_YEAR, 1);
                    dayInfo.setEndDate(calendar.getTime());
                    eventsInfoList.add(dayInfo);
                }
            }
        } else if (diffDay < 180) {
            //前3个按周给，后面的按月
            if(diffDay < 21){
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(simpleDateFormat.parse(eventsInfoReq.getStartDate()));
                for(int i =0;i<diffDay ;i++){
                    EventsInfo dayInfo = new EventsInfo();
                    dayInfo.setStartDate(calendar.getTime());
                    calendar.add(Calendar.WEEK_OF_YEAR, 1);
                    dayInfo.setEndDate(calendar.getTime());
                    eventsInfoList.add(dayInfo);

                }
            }else{
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(simpleDateFormat.parse(eventsInfoReq.getStartDate()));

                for (int i = 0; i < 3; i++) {
                    EventsInfo dayInfo = new EventsInfo();
                    dayInfo.setStartDate(calendar.getTime());
                    calendar.add(Calendar.WEEK_OF_YEAR, 1);
                    dayInfo.setEndDate(calendar.getTime());
                    eventsInfoList.add(dayInfo);
                }


                while (calendar.getTime().before(eventsInfo.getEndDate())) {
                    EventsInfo dayInfo = new EventsInfo();
                    dayInfo.setStartDate(calendar.getTime());
                    calendar.add(Calendar.MONTH, 1);
                    dayInfo.setEndDate(calendar.getTime());
                    eventsInfoList.add(dayInfo);
                }
            }
        }else {
            //前3个按月给，后面的按半年
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(eventsInfo.getStartDate());

            for (int i = 0; i < 3; i++) {
                EventsInfo dayInfo = new EventsInfo();
                dayInfo.setStartDate(calendar.getTime());
                calendar.add(Calendar.MONTH, 1);
                dayInfo.setEndDate(calendar.getTime());
                eventsInfoList.add(dayInfo);
            }


            while (calendar.getTime().before(simpleDateFormat.parse(eventsInfoReq.getEndDate()))) {
                EventsInfo dayInfo = new EventsInfo();
                dayInfo.setStartDate(calendar.getTime());
                calendar.add(Calendar.MONTH, 6);
                dayInfo.setEndDate(calendar.getTime());
                eventsInfoList.add(dayInfo);
            }
        }
        LambdaQueryWrapper<MapInfo> mapInfoQueryWrapper = new LambdaQueryWrapper<>();
        Calendar calendar = Calendar.getInstance();
        for (EventsInfo dayInfo : eventsInfoList ) {
            calendar.setTime(dayInfo.getEndDate());
            calendar.set(Calendar.HOUR,23);
            calendar.set(Calendar.MINUTE,59);
            calendar.set(Calendar.SECOND,59);
            mapInfoQueryWrapper.ge(MapInfo::getItemAccessTime, dayInfo.getStartDate());
            mapInfoQueryWrapper.le(MapInfo::getItemAccessTime, calendar.getTime());
            if (eventsInfoReq.getKeywords()!= null && eventsInfoReq.getKeywords().length > 0) {
                mapInfoQueryWrapper.in(MapInfo::getKeywords, eventsInfoReq.getKeywords()); // 使用in进行Keywords筛选
            }
            dayInfo.setInfoNum(MapInfoMapper.selectCount(mapInfoQueryWrapper));
            mapInfoQueryWrapper.clear();
        }
        return eventsInfoList;
    }

    @Override
    public List<EventsInfo> getAllEvents() {
        return EventsInfoMapper.selectList(new LambdaQueryWrapper<>());
    }

//    @Override
//    public Boolean cityUpdateLocation(String city) {
//        LambdaQueryWrapper<LocationInfo> queryWrapper = new LambdaQueryWrapper<>();
//        if(!Objects.isNull(city)){
//            queryWrapper.eq(LocationInfo::getCity,city);
//        }
//        List<LocationInfo> locationInfoList = LocationInfoMapper.selectList(queryWrapper);
////        List<LocationInfo> newLocationInfoList = new ArrayList<>();
//        for(LocationInfo locationInfo : locationInfoList){
////            newLocationInfoList.add(updateLocationByAPI(locationInfo));
//            LocationInfoMapper.updateById(updateLocationByAPI(locationInfo));
//        }
//        return true;
//    }

//    private LocationInfo updateLocationByAPI(LocationInfo locationInfo){
//        try {
//            // 发送HTTP GET请求
//            URL url = new URL("https://maps.googleapis.com/maps/api/geocode/json?address=" + locationInfo.getCity());
//            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//            connection.setRequestMethod("GET");
//
//            // 读取响应
//            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
//            StringBuilder response = new StringBuilder();
//            String line;
//            while ((line = reader.readLine()) != null) {
//                response.append(line);
//            }
//            reader.close();
//
//            // 解析JSON响应
//            JSONObject jsonResponse = new JSONObject(response.toString());
//            double lat = jsonResponse.getJSONArray("results").getJSONObject(0).getJSONObject("geometry")
//                    .getJSONObject("location").getDouble("lat");
//            double lng = jsonResponse.getJSONArray("results").getJSONObject(0).getJSONObject("geometry")
//                    .getJSONObject("location").getDouble("lng");
//            locationInfo.setLat(lat);
//            locationInfo.setLng(lng);
////            System.out.println("纬度：" + lat);
////            System.out.println("经度：" + lng);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return locationInfo;
//    }


}

